<?php

namespace common\widgets\grid;

use Yii;
use yii\base\Arrayable;
use yii\base\InvalidConfigException;
use yii\base\Model;
use yii\base\Widget;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
use yii\helpers\Inflector;
use yii\i18n\Formatter;
use common\widgets\ConsoleActions;

/**
 * DetailView displays the detail of a single data [[model]].
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
class FlexDetailView extends \yii\widgets\DetailView {

    public $captionOptions = [
        'class' => 'font-weight-bolder mr-2',
    ];
    public $contentOptions = [];
    public $theader = false;

    /**
     * @var array the HTML attributes for the container tag of this widget. The `tag` option specifies
     * what container tag should be used. It defaults to `table` if not set.
     * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
     */
    public $options = [
        'tag' => 'div'
    ];
    public $itemOptions = [
        'class' => 'd-flex justify-content-between align-items-center mb-2',
    ];
    protected $rowOptions;

    /**
     * @var string|callable the template used to render a single attribute. If a string, the token `{label}`
     * and `{value}` will be replaced with the label and the value of the corresponding attribute.
     * If a callback (e.g. an anonymous function), the signature must be as follows:
     *
     * ```php
     * function ($attribute, $index, $widget)
     * ```
     *
     * where `$attribute` refer to the specification of the attribute being rendered, `$index` is the zero-based
     * index of the attribute in the [[attributes]] array, and `$widget` refers to this widget instance.
     *
     * Since Version 2.0.10, the tokens `{captionOptions}` and `{contentOptions}` are available, which will represent
     * HTML attributes of HTML container elements for the label and value.
     */
    public $template = '<div{itemOptions}><span{captionOptions}>{label}</span><span{contentOptions}>{value}</span></div>'; //[self::class, 'renderTemplate'];

    /**
     * @var boolean whether to show the grid view if [[dataProvider]] returns no data.
     */
    public $showOnEmpty = true;

    /**
     * @var boolean whether to show the grid view if [[dataProvider]] returns no data.
     */
    public $showConsoles = false;

    /**
     * @var string the HTML display when the content of a cell is empty.
     * This property is used to render cells that have no defined content,
     * e.g. empty footer or filter cells.
     *
     * Note that this is not used by the [[DataColumn]] if a data item is `null`. In that case
     * the [[\yii\i18n\Formatter::nullDisplay|nullDisplay]] property of the [[formatter]] will
     * be used to indicate an empty data value.
     */
    public $emptyCell = '&nbsp;';

    /**
     * Initializes the detail view.
     * This method will initialize required property values.
     */
    public function init() {
        parent::init();
        $itemOptions = ArrayHelper::merge(ArrayHelper::remove($this->options, 'itemOptions', []), $this->itemOptions);
        $this->rowOptions = Html::renderTagAttributes($itemOptions);
        $this->trigger(self::EVENT_INIT);
    }

    /**
     * Renders a single attribute.
     * @param array $attribute the specification of the attribute to be rendered.
     * @param int $index the zero-based index of the attribute in the [[attributes]] array
     * @param int $widget the zero-based index of the attribute in the [[attributes]] array
     * @return string the rendering result
     */
    protected function renderTemplate($attribute, $index, $widget) {
        return '123';
    }

    /**
     * Renders the detail view.
     * This is the main entry of the whole detail view rendering.
     */
    public function run() {
        $view = $this->getView();
        DetailViewAsset::register($view);
        $content = [
            $this->renderTheader(),
        ];
        if ($this->model) {
            $content[] = $this->renderTbody();
        } else {
            $content[] = $this->renderEmpty();
        }
        $tag = ArrayHelper::remove($this->options, 'tag', 'table');
        return Html::tag($tag, implode("\n", array_filter($content)), $this->options);
    }

    protected function renderEmpty() {
        if (!$this->showOnEmpty) {
            return null;
        }
        return "<tbody><tr><td colspan='2' class='empty'>{$this->emptyCell}</td></tr></tbody>";
    }

    protected function renderTheader() {
        if ($this->theader === false) {
            return null;
        }
        return "<thead><tr><th colspan='2'>{$this->theader}</th></tr></thead>";
    }

    protected function renderTbody() {
        $rows = [];
        $i = 0;
        foreach ($this->attributes as $attribute) {
            $rows[] = $this->renderAttribute($attribute, $i++);
        }
        if ($this->showConsoles === true && $this->model->hasMethod('getConsoles')) {
            $rows[] = $this->renderAttributeConsoles($i++);
        }
        return "<tbody>\n" . implode("\n", $rows) . "\n</tbody>";
    }

    protected function renderAttributeConsoles($index) {
        $consoles = ConsoleActions::widget([
            'options' => ['class' => 'btn-group btn-group-devided'],
            'items' => $this->model->getConsoles()
        ]);
        return $this->renderAttribute([
            'attribute' => 'consoles',
            'label' => '操作',
            'format' => 'raw',
            'value' => $consoles
        ], $index);
    }

    /**
     * Renders a single attribute.
     * @param array $attribute the specification of the attribute to be rendered.
     * @param int $index the zero-based index of the attribute in the [[attributes]] array
     * @return string the rendering result
     */
    protected function renderAttribute($attribute, $index) {
        if (is_string($this->template)) {
            $captionOptions = Html::renderTagAttributes(ArrayHelper::getValue($attribute, 'captionOptions', $this->captionOptions));
            $contentOptions = Html::renderTagAttributes(ArrayHelper::getValue($attribute, 'contentOptions', $this->contentOptions));
            return strtr($this->template, [
                '{label}' => $attribute['label'],
                '{value}' => $this->formatter->format($attribute['value'], $attribute['format']),
                '{captionOptions}' => $captionOptions,
                '{contentOptions}' => $contentOptions,
                '{itemOptions}' => $this->rowOptions,
            ]);
        }
        return call_user_func($this->template, $attribute, $index, $this);
    }

}
